import type { questionSideListState, diyRuleState, dyFormOptionsState } from '@/types/baseConfig'
import type { addRuleState } from '@/types/form'
import type { FormItemRule } from 'naive-ui'
import { deepClone } from '@/utils/index'
import { nanoid } from 'nanoid'
import { getValue } from '@/enum/slotNameEnum'
import valiDate from '@/utils/validate'

export function getQuestionsInfo(el: questionSideListState) {
  el.uid = nanoid()
  el.commonForm.labelKey = el.uid
  return el
}
export function getOptions(questions: questionSideListState[]) {
  return deepClone(questions)
    .map((el: questionSideListState) => {
      let options: dyFormOptionsState[] = [
        {
          labelKey: el.commonForm.labelKey,
          labelName: `${el.commonForm.labelKey}(${el.commonForm.labelName})`,
          dataType: 'string'
        }
      ]
      if (el.RowLayoutForm && el.RowLayoutForm.childer.length > 0) {
        const childerOptins: dyFormOptionsState[] = getOptions(el.RowLayoutForm.childer)
        options = [...options, ...childerOptins]
      }
      return options
    })
    .flat()
}

/**
 *  获取组件slot数组
 * */
export function getSlotName(
  questions: questionSideListState[],
  leaverOne = true,
  newInfo: any = {}
) {
  deepClone(questions).forEach((el: questionSideListState) => {
    const name: string = keyToSlotName(el.commonForm.labelKey)
    if (el.type === 'RowLayout' && el.RowLayoutForm && el.RowLayoutForm.childer.length > 0) {
      const rowNewInfo = getSlotName(el.RowLayoutForm.childer, false)
      newInfo[el.commonForm.labelKey] = Object.values(rowNewInfo).flat()
      newInfo = {
        ...newInfo,
        ...rowNewInfo
      }
    } else {
      const arr: string[] = getValue(el.type)
      const slotArr: string[] = []
      if (arr.length > 0) {
        arr.forEach((el: string) => {
          slotArr.push(`${name}_${el}`)
        })
      }
      if (!leaverOne) {
        slotArr.unshift(name)
      }
      newInfo[el.commonForm.labelKey] = slotArr
    }
  })
  return newInfo
}

export function keyToSlotName(str: string) {
  return str.replaceAll('.', '_')
}
/**
 *  根据key获取删除以及子对象值
 *  示例  key: userInfo.test.age
 * */
export function deleteNestedProperty(obj: any, propertyPath: string) {
  const pathParts = propertyPath.split('.')
  if (pathParts.length === 1) {
    delete obj[pathParts[0]]
  } else {
    deleteNestedProperty(obj[pathParts[0]], pathParts.slice(1).join('.'))
  }
}

/**
 *  根据key获取对象以及子对象值
 *  示例  key: userInfo.test.age
 * */
export function getRowValue(row: any, key: string) {
  let value = null
  if (key.includes('.')) {
    const labelKeyArr = key.split('.')
    let info = row
    try {
      labelKeyArr.forEach((el: string, index: number) => {
        if (index === labelKeyArr.length - 1) {
          value = info[el]
        } else {
          if (info[el]) {
            info = info[el]
          } else {
            throw Error('值为空')
          }
        }
      })
    } catch (e) {
      value = null
    }
  } else {
    value = row[key]
  }
  return value
}

/**
 *  获取子对象
 * */
export function getChilderParams(
  labelKeyArr: string[],
  index: number,
  childerParams: any,
  defaultValue: any
) {
  if (index === labelKeyArr.length - 1) {
    childerParams[labelKeyArr[index]] = defaultValue
  } else if (!childerParams[labelKeyArr[index]]) {
    childerParams[labelKeyArr[index]] = getChilderParams(labelKeyArr, index + 1, {}, defaultValue)
  }
  return childerParams
}

export function getQueryForm(questions: questionSideListState[]) {
  let params: any = {}
  questions.forEach((el: questionSideListState) => {
    if (el.type === 'RowLayout') {
      if (el.RowLayoutForm) {
        params = {
          ...params,
          ...getQueryForm(el.RowLayoutForm?.childer)
        }
      }
    } else {
      params[el.commonForm.labelKey] = el.commonForm.defaultValue
    }
  })
  return params
}

/**
 *  合并对象以及子对象
 * */
export function mergeParams(oldParams: any, newParams: any) {
  Object.keys(newParams).forEach((item: string) => {
    if (newParams[item]?.constructor === Object) {
      if (!oldParams[item]) {
        oldParams[item] = newParams[item]
      } else {
        oldParams[item] = mergeParams(oldParams[item], newParams[item])
      }
    } else {
      oldParams[item] = newParams[item]
    }
  })
  return oldParams
}

export function getRule(el: questionSideListState, queryForm: any, isText = false) {
  const rules = []
  if (el?.ruleInfo && el.ruleInfo.isRules) {
    if (el.ruleInfo.isRequired) {
      const ruleInfo = {
        required: true,
        validator(rule: FormItemRule, value: any) {
          if (value === undefined || value === null || value === '') {
            return new Error(el.ruleInfo?.requiredTip || '不能为空')
          }
          return true
        },
        trigger: el.ruleInfo.trigger
      }
      rules.push(
        isText
          ? `{
              required: true,
              message: '${el.ruleInfo?.requiredTip || '不能为空'}',
              trigger: '${el.ruleInfo.trigger}'
            }`
          : ruleInfo
      )
    }
    if (el.ruleInfo.regex) {
      const ruleInfo = {
        validator(rule: FormItemRule, value: any) {
          if (el.ruleInfo?.regex) {
            if (el.ruleInfo?.regex.includes('is')) {
              if (!valiDate[el.ruleInfo.regex](value)) {
                return new Error(el.ruleInfo?.regexTip)
              }
            } else if (!eval(el.ruleInfo?.regex || '').test(value)) {
              return new Error(el.ruleInfo?.regexTip)
            }
          }
          return true
        },
        trigger: el.ruleInfo.trigger
      }
      rules.push(ruleInfo)
    }
    if (el.ruleInfo.diyRule && el.ruleInfo.diyRule.length > 0) {
      const ruleInfo = {
        validator(rule: FormItemRule, value: any) {
          const arr: any = deepClone(el.ruleInfo?.diyRule).map((item: diyRuleState) => {
            const errorArr: any = []
            item.childer.find((element: addRuleState) => {
              const rowValue = element.isItem
                ? getRowValue(queryForm, element.labelKey)
                : element.value
              switch (element.way) {
                case 'noeqEmpty':
                  if (value === undefined || value === null) {
                    errorArr.push(element)
                  }
                  break
                case 'eq':
                  if (value !== rowValue) {
                    errorArr.push(element)
                  }
                  break
                case 'noeq':
                  if (value === rowValue) {
                    errorArr.push(element)
                  }
                  break
                case 'gt':
                  if (value <= rowValue) {
                    errorArr.push(element)
                  }
                  break
                case 'lt':
                  if (value >= rowValue) {
                    errorArr.push(element)
                  }
                  break
                case 'includes':
                  if (!rowValue.includes(value)) {
                    errorArr.push(element)
                  }
                  break
                case 'noincludes':
                  if (rowValue.includes(value)) {
                    errorArr.push(element)
                  }
                  break
              }
            })
            return errorArr
          })
          const status = arr.some((el: any) => el.length === 0)
          if (status) return true
          const info = arr.find((el: any) => el.length > 0)
          return new Error(info[0].errTip)
        },
        trigger: el.ruleInfo.trigger
      }
      if (isText) {
        let textRule = `
            {
              validator(rule: FormItemRule, value: any){ `
        el.ruleInfo?.diyRule.forEach((item: diyRuleState) => {
          item.childer.forEach((element: addRuleState) => {
            if (element.isItem) {
              textRule += `
                if`
              switch (element.way) {
                case 'eq':
                  textRule += `(value !== queryForm.value.${element.labelKey})`
                  break
                case 'noeq':
                  textRule += `(value === queryForm.value.${element.labelKey})`
                  break
                case 'gt':
                  textRule += `(value <= queryForm.value.${element.labelKey})`
                  break
                case 'lt':
                  textRule += `(value >= queryForm.value.${element.labelKey})`
                  break
                case 'includes':
                  textRule += `(!queryForm.value.${element.labelKey}.includes(value))`
                  break
                case 'noincludes':
                  textRule += `(queryForm.value.${element.labelKey}.includes(value))`
                  break
              }
              textRule += ` {
                  return new Error('${element.errTip}')
                }`
            } else {
              textRule += `
                if`
              switch (element.way) {
                case 'eq':
                  textRule += `(value !== ${element.value})`
                  break
                case 'noeq':
                  textRule += `(value === ${element.value})`
                  break
                case 'gt':
                  textRule += `(value <= ${element.value})`
                  break
                case 'lt':
                  textRule += `(value >= ${element.value})`
                  break
                case 'includes':
                  textRule += `(!${element.value}.includes(value))`
                  break
                case 'noincludes':
                  textRule += `(${element.value}.includes(value))`
                  break
              }
              textRule += ` {
                  return new Error('${element.errTip}')
                }`
            }
          })
        })
        textRule += `
              },
              trigger: '${el.ruleInfo.trigger}'
            }`
        rules.push(textRule)
      } else {
        rules.push(ruleInfo)
      }
    }
  }
  return rules
}

export function queryFormTo(queryForm: any) {
  let params: any = {}
  const keys = Object.keys(queryForm).sort()
  keys.forEach((el: any) => {
    if (el.includes('.')) {
      const labelKeyArr = el.split('.')
      const newParams = getChilderParams(labelKeyArr, 0, {}, queryForm[el])
      params = mergeParams(params, newParams)
    } else {
      params[el] = queryForm[el]
    }
  })
  return params
}

export function getFromTypeKeys(questions: questionSideListState[]) {
  let arr: string[] = []
  questions.forEach((el: questionSideListState) => {
    if (el.type === 'RowLayout') {
      if (el.RowLayoutForm) {
        arr = [...arr, ...getFromTypeKeys(el.RowLayoutForm?.childer)]
      }
    } else if (
      el.type === 'SelectInput' &&
      !el.SelectInputForm?.remote &&
      el.SelectInputForm?.fromTypeKey
    ) {
      arr.push(el.SelectInputForm?.fromTypeKey)
    }
  })
  return arr
}
